#ifndef CONFIG_READER_WRITER_HEADER
#define CONFIG_READER_WRITER_HEADER

#include <atlmisc.h>

class CSettingReaderWriter {

    struct DatabaseSetting {
        WTL::CString host;
        WTL::CString name;
        WTL::CString user;
        WTL::CString passwd;
    } db_setting_;

    struct TaskSetting {
        WTL::CString owner;
        WTL::CString download_dir;
        USHORT speed_limit;
        USHORT concurrent_task;
        USHORT max_retry;
        USHORT schedule_interval;
    } task_setting_;

protected:

    WTL::CString GetSettingFileName()
    {
        WTL::CString _filename;
        TCHAR _tchs[MAX_PATH] = { 0 };

        GetModuleFileName(NULL, _tchs, MAX_PATH);
        PathRemoveFileSpec(_tchs);
        _filename.Format(_T("%s\\Settings.ini"), _tchs);
        return _filename;
    }

public:

    void load_conf()
    {
        TCHAR _tvals[32] = { 0 };
        WTL::CString _filename = GetSettingFileName();

        GetPrivateProfileString(_T("database"), _T("host"), _T(""),
            _tvals, sizeof(_tvals) - 1, _filename);
        db_setting_.host = _tvals;
        GetPrivateProfileString(_T("database"), _T("name"), _T(""),
            _tvals, sizeof(_tvals) - 1, _filename);
        db_setting_.name = _tvals;
        GetPrivateProfileString(_T("database"), _T("user"), _T(""),
            _tvals, sizeof(_tvals) - 1, _filename);
        db_setting_.user = _tvals;
        GetPrivateProfileString(_T("database"), _T("passwd"), _T(""),
            _tvals, sizeof(_tvals) - 1, _filename);
        db_setting_.passwd = _tvals;

        task_setting_.owner = GetPrivateProfileString(_T("task"), 
            _T("owner"), _T(""), _tvals, sizeof(_tvals) - 1, _filename);
        task_setting_.owner = _tvals;

        GetPrivateProfileString(_T("task"), _T("download_dir"), _T(""),
            _tvals, sizeof(_tvals) - 1, _filename);
        task_setting_.download_dir = _tvals;

        task_setting_.concurrent_task = GetPrivateProfileInt(_T("task"),
            _T("concurrent_task"), 10, _filename);
        /*
        task_setting_.speed_limit = GetPrivateProfileInt(_T("task"),
            _T("speed_limit"), 10, _filename);
        task_setting_.max_retry = GetPrivateProfileInt(_T("task"),
            _T("max_retry"), 10, _filename);
        */
        task_setting_.schedule_interval = GetPrivateProfileInt(_T("task"),
            _T("schedule_interval"), 300, _filename);
    }

    void save_conf()
    {
        WTL::CString _sval;
        WTL::CString _filename = GetSettingFileName();

        WritePrivateProfileString(_T("database"), _T("host"),
            db_setting_.host, _filename);
        WritePrivateProfileString(_T("database"), _T("name"),
            db_setting_.name, _filename);
        WritePrivateProfileString(_T("database"), _T("user"),
            db_setting_.user, _filename);
        WritePrivateProfileString(_T("database"), _T("passwd"),
            db_setting_.passwd, _filename);

        WritePrivateProfileString(_T("task"), _T("owner"),
            task_setting_.owner, _filename);

        WritePrivateProfileString(_T("task"), _T("download_dir"),
            task_setting_.download_dir, _filename);

        _sval.Format(_T("%d"), task_setting_.concurrent_task);
        WritePrivateProfileString(_T("task"), _T("concurrent_task"),
            _sval, _filename);
        /*
        _sval.Format(_T("%d"), task_setting_.speed_limit);
        WritePrivateProfileString(_T("task"), _T("speed_limit"),
            _sval, _filename);
        _sval.Format(_T("%d"), task_setting_.max_retry);
        WritePrivateProfileString(_T("task"), _T("max_retry"),
            _sval, _filename);
        */
        _sval.Format(_T("%d"), task_setting_.schedule_interval);
        WritePrivateProfileString(_T("task"), _T("schedule_interval"),
            _sval, _filename);
    }

public:

    CSettingReaderWriter()
    {
        load_conf();
    }

    bool is_db_conf_ok() 
    {
        return !GetHost().IsEmpty() && !GetName().IsEmpty() &&
                !GetUser().IsEmpty();// && !GetPasswd().IsEmpty();
    }

    bool is_task_conf_ok()
    {
        return !GetDownloadDir().IsEmpty() && !GetOwner().IsEmpty();
    }

#define DECLARE_PROPERTY(type, var, value)   \
    type Get##var()                 { return value; }   \
    void Set##var(const type &v)    { value = v; }

    DECLARE_PROPERTY(WTL::CString, Host, db_setting_.host)
    DECLARE_PROPERTY(WTL::CString, Name, db_setting_.name)
    DECLARE_PROPERTY(WTL::CString, User, db_setting_.user)
    DECLARE_PROPERTY(WTL::CString, Passwd, db_setting_.passwd)

    DECLARE_PROPERTY(WTL::CString, Owner, task_setting_.owner)
    DECLARE_PROPERTY(WTL::CString, DownloadDir, task_setting_.download_dir)
    DECLARE_PROPERTY(USHORT, SpeedLimit, task_setting_.speed_limit)
    DECLARE_PROPERTY(USHORT, ConcurrentTask, task_setting_.concurrent_task)
    DECLARE_PROPERTY(USHORT, MaxRetry, task_setting_.max_retry)
    DECLARE_PROPERTY(USHORT, SchedIntrv, task_setting_.schedule_interval)

};

#endif